import os
import pandas as pd
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Dict
from datetime import datetime, date

weeks = [
        (date(2012,5,7), date(2012,5,13)), 
        (date(2012,6,4), date(2012,6,10)), 
        (date(2012,7,2), date(2012,7,8)), 
        (date(2012,8,6), date(2012,8,12))
]

days = [
        date(2012,5,7), date(2012,5,8), date(2012,5,9), date(2012,5,10), date(2012,5,11), date(2012,5,12),date(2012,5,13), 
        date(2012,6,4), date(2012,6,5), date(2012,6,6), date(2012,6,7), date(2012,6,8), date(2012,6,9), date(2012,6,10),
        date(2012,7,2), date(2012,7,3), date(2012,7,4), date(2012,7,5), date(2012,7,6), date(2012,7,7), date(2012,7,8),
        date(2012,8,6), date(2012,8,7), date(2012,8,8), date(2012,8,9), date(2012,8,10), date(2012,8,11), date(2012,8,12)
]

@dataclass
class Log:
    start_time: datetime
    duration: int
    activities: List[Dict[str, str]] = field(default_factory=list)

@dataclass
class Software:
    date: date
    name: str
    time: int
    platform: str

@dataclass
class UserDescribe:
    user_id:str
    user_info: dict = field(default_factory=dict)
    user_logs: list[Log] = field(default_factory=list)
    user_softwares: dict[datetime.date, list[Software]] = field(default_factory=dict)
    process_mapping: dict[str, str] = field(default_factory=dict)
    
    def __post_init__(self):
        self.load_user_info()
        self.load_user_logs()
        self.load_user_software()

    def load_user_info(self):
        df = pd.read_csv("data/demographic.csv")
        self.user_info = df[df['USERID'].astype("str") == (self.user_id)]

    def load_user_log(self,log_path:str) -> Log:
        path = Path(log_path)
        with path.open('r', encoding='utf-8') as f:
            lines = [line.strip() for line in f.readlines()]
        duration = int(lines[0].split("<=>")[1])
        start_time = datetime.strptime(lines[1].split("<=>")[1], "%Y-%m-%d %H-%M-%S")
        activities = []
        self.process_mapping["explorer.exe"] = {
                    'N': '文件资源管理器',
                    'C': '',
                }
        for line in lines[2:]:
            activity = {}
            pairs = line.split("[=]")
            for pair in pairs:
                key, value = pair.split("<=>", 1)
                activity[key] = value
            activities.append(activity)
            process_name = activity["P"]
            if process_name not in self.process_mapping:
                self.process_mapping[process_name] = {
                    'N': activity.get("N", process_name),
                    'C': activity.get("C"),
                }
            duration = max(int(activity["T"]), duration)
        activities.sort(key=lambda x: int(x['T']))
        if duration != int(lines[0].split("<=>")[1]):
            duration += 2
        return Log(
            start_time = start_time,
            duration = duration,
            activities = activities
        )
    
    def load_user_logs(self):
        for date_folder in os.listdir("data/processed"):
            date_path = os.path.join("data/processed", date_folder)
            for filename in os.listdir(date_path):
                parts = filename.split('_')
                file_user_id = parts[0]
                if file_user_id == self.user_id:
                    full_path = os.path.join(date_path,filename).replace('\\', '/')
                    self.user_logs.append(self.load_user_log(full_path))

    def load_user_software(self):
        tmp: dict[tuple[tuple[datetime,str]],Software] = {}
        for log in self.user_logs:
            date = log.start_time.date()
            activities = log.activities

            for i in range(len(activities)):
                activity = activities[i]
                name = self.process_mapping[activity.get("P")]["N"]
                platform = "computer"
                if activity.get("U") is not None:
                    platform = name
                    name = activity.get("U")
                curr_time = int(activity.get("T"))
                if i < len(activities) - 1:
                    next_time = int(activities[i + 1].get("T"))
                    time = next_time - curr_time
                else:
                    time = log.duration - curr_time
                
                key = (date, name)
                if key not in tmp:
                    tmp[key] = Software(
                        date=date,
                        name=name,
                        time=time,
                        platform=platform
                    )
                else:
                    tmp[key].time += time

        date_dict = {}
        for software in tmp.values():
            if software.date not in date_dict:
                date_dict[software.date] = []
            date_dict[software.date].append(software)
        self.user_softwares = date_dict